package org.timeticker.gui;

import org.timeticker.*;
import org.apache.log4j.Logger;

import javax.swing.table.AbstractTableModel;
import javax.swing.event.TableModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.*;
import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Method;

/**
 * Object list table model
 *
 * @author Ivan Latysh
 * @version 0.1
 * @since 11-Jul-2007 : 9:25:31 PM
 */
public abstract class ObjectListTableModel<T> extends AbstractTableModel implements ObjectListListener {
  // Error prefix OLTM00003

  /** Component logger */
  protected Logger logger = Logger.getLogger(this.getClass().getName());
  /** Columns */
  protected final List<ObjectListTableModelColumn> columns = new ArrayList<ObjectListTableModelColumn>();
  /** Listeners */
  protected final List<TableModelListener> listeners = new ArrayList<TableModelListener>();
  /** Object list */
  private ObjectList<T> objects;

  /**
   * Create a new blank table model
   *
   * @see #setObjects(org.timeticker.ObjectList) 
   */
  protected ObjectListTableModel() {
  }

  /**
   * Create a new table model with given object list
   *
   * @param objects objects
   */
  protected ObjectListTableModel(ObjectList<T> objects) {
    setObjects(objects);
  }

  /**
   * Set object list to be used by this table model
   *
   * @param objects object list
   */
  public void setObjects(ObjectList<T> objects) {
    // remove us from old object list
    if (null!=this.objects && this.objects != objects) this.objects.removeListener(this);
    // update object list
    this.objects = objects;
    // attach this model to object list
    objects.addListener(this);
  }

  /**
   * Return object list
   *
   * @return objects
   */
  public final ObjectList<T> getObjects() {
    return objects;
  }

  /**
   * Return Object at row
   *
   * @param row row
   * @return object
   */
  public T getObjectAtRow(int row) {
    return objects.get(row);
  }

  public int getRowCount() {
    return objects.size();
  }

  public int getColumnCount() {
    return columns.size();
  }

  public String getColumnName(int columnIndex) {
    return columns.get(columnIndex).getName();
  }

  public Class<?> getColumnClass(int columnIndex) {
    return columns.get(columnIndex).getClazz();
  }

  public boolean isCellEditable(int rowIndex, int columnIndex) {
    return false;
  }

  public Object getValueAt(int rowIndex, int columnIndex) {
    return BeanHelper.getPropertyValue(objects.get(rowIndex), columns.get(columnIndex).getPropertyName());
  }

  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    //
  }

  protected void fireTableModelEvent(final TableModelEvent event) {
    // execute event dispatching in EventDispatchThread
    if (SwingUtilities.isEventDispatchThread()) {
      fireTableChanged(event);
    } else {
      SwingUtilities.invokeLater(new Runnable(){
        public void run() {
          fireTableChanged(event);
        }
      });
    }
  }

  /** {@inheritDoc} */
  public void objectAdded(ObjectList list, int index, Object object) {
    fireTableModelEvent(new TableModelEvent(this));
  }

  public void objectRemoved(ObjectList list, int index, Object object) {
    fireTableModelEvent(new TableModelEvent(this));
  }

  public void objectChanged(ObjectList list, int index, Object object) {
    fireTableModelEvent(new TableModelEvent(this));
  }

  public void listChanged(ObjectList list) {
    fireTableModelEvent(new TableModelEvent(this));
  }

}
